/**************************************************************************//**
 * @item     CosyOS Kernel
 * @file     usv_loc.c
 * @brief    Service for User Task is to be executed locally
 * @author   迟凯峰
 * @version  V2.0.0
 * @date     2023.03.07
 ******************************************************************************/

#include "glovar.h"
#include "sysapi.h"
#include "svs.h"

void __enter_critical(void)
{
	mEnterCritical;
}

bool __enter_critical_r(void)
{
	mEnterCritical;
	return true;
}

void __exit_critical(void)
{
	mExitCritical;
}

void __start_task(tspTaskHandle thdl, u8 state)
{
	static tTID tid = 0;
	if(!thdl->TID)
	{
		tid++;
		thdl->TID = tid;
	}
	#if SYSCFG_TASKCREATEMODE == __STATIC__
	thdl->state = state;
	#elif SYSCFG_TASKCREATEMODE == __DYNAMIC__
	thdl->TNOD = (tspTaskNode)state;
	#endif
	vACTBUF = thdl;
	vScheduling_f = true;
	mPSV_Trigger;
	__exit_critical();
}

void __resume_task(tspTaskNode node)
{
	if(node->state & __SUSPENDED__)
	{
		node->state &= __RESUME__;
		if(node->state <= __FLOATING__ && node->TPL > vTASKING->TPL)
		{
			vScheduling_f = true;
			mPSV_Trigger;
		}
	}
	__exit_critical();
}

void __suspend_task(tspTaskNode node)
{
	if(node->state < __SUSPENDED__)
	{
		node->state |= __SUSPENDED__;
		if(node == vTASKING)
		{
			vScheduling_f = true;
			mPSV_Trigger;
		}
	}
	__exit_critical();
}

void __delete_task(tspTaskNode node)
{
	node->state = __DELETED__;
	if(node == vTASKING)
	{
		vScheduling_f = true;
		mPSV_Trigger;
	}
	__exit_critical();
}

void __ressus_task(tspTaskNode node)
{
	if(node->state & __SUSPENDED__)
	{
		node->state &= __RESUME__;
	}
	vTASKING->state |= __SUSPENDED__;
	vScheduling_f = true;
	mPSV_Trigger;
	__exit_critical();
}

void __set_priority(tspTaskNode node, u8 tpl)
{
	mEntry_Monitor;
	vTPLBUF[node->TID] = tpl;
	vTPLSUM++;
	if(node == vTASKING || node->state <= __FLOATING__ && tpl > vTASKING->TPL)
	{
		vScheduling_f = true;
		mPSV_Trigger;
	}
	__exit_critical();
}

void __delay(tDelay tc)
{
	if(tc)
	{
		vDELAY_STMR[vTASKING->TID] = tc;
		vTASKING->blocktype = __DELAY__;
		vTASKING->state = __BLOCKED__;
	}
	vScheduling_f = true;
	mPSV_Trigger;
	__exit_critical();
}

void __free_mut(volatile tsMut *p)
{
	mEntry_Monitor;
	if(vTASKING->TID == p->TID)
	{
		p->mut = true;
		if(vTASKING->TPL > p->TPL)
		{
			vTPLBUF[p->TID] = p->TPL;
			vTPLSUM++;
			vScheduling_f = true;
			mPSV_Trigger;
		}
	}
	__exit_critical();
}

bool __take_mut(volatile tsMut *p, tDelay tc)
{
	mEntry_Monitor;
	if(p->mut)
	{
		p->mut = false;
		p->TID = vTASKING->TID;
		p->TPL = vTASKING->TPL;
		p->tpl = vTASKING->TPL;
		__exit_critical();
		return true;
	}
	else if(tc)
	{
		vDELAY_STMR[vTASKING->TID] = tc;
		vTASKING->blocktype = ~tc ? __MUTEX__ | __DELAY__ : __MUTEX__;
		vTASKING->state = __BLOCKED__;
		vTASKING->ptr = (void *)p;
		if(vTASKING->TPL > p->tpl)
		{
			p->tpl = vTASKING->TPL;
			vTPLBUF[p->TID] = vTASKING->TPL;
			vTPLSUM++;
		}
		vScheduling_f = true;
		mPSV_Trigger;
		__exit_critical();
		return (bool)vTASKING->blocktype;
	}
	else
	{
		__exit_critical();
		return false;
	}
}

bool __take_bin(volatile bool *p, tDelay tc, u8 type)
{
	mEntry_Monitor;
	if(*p)
	{
		if(type == __BINARY_TAKE__)
		{
			*p = false;
		}
		__exit_critical();
		return true;
	}
	else if(tc)
	{
		vDELAY_STMR[vTASKING->TID] = tc;
		vTASKING->blocktype = ~tc ? type | __DELAY__ : type;
		vTASKING->state = __BLOCKED__;
		vTASKING->ptr = (void *)p;
		vScheduling_f = true;
		mPSV_Trigger;
		__exit_critical();
		return (bool)vTASKING->blocktype;
	}
	else
	{
		__exit_critical();
		return false;
	}
}

bool __take_sem(volatile tspSem p, tDelay tc)
{
	mEntry_Monitor;
	if(p->counter)
	{
		p->counter--;
		__exit_critical();
		return true;
	}
	else if(tc)
	{
		vDELAY_STMR[vTASKING->TID] = tc;
		vTASKING->blocktype = ~tc ? __SEMAPHORE__ | __DELAY__ : __SEMAPHORE__;
		vTASKING->state = __BLOCKED__;
		vTASKING->ptr = (void *)p;
		vScheduling_f = true;
		mPSV_Trigger;
		__exit_critical();
		return (bool)vTASKING->blocktype;
	}
	else
	{
		__exit_critical();
		return false;
	}
}

#if SYSCFG_DIRMSG == __ENABLED__

bool __recv_dm(tDM *m0_, tDM *m1, size_t size, tDelay tc)
{
	mEntry_Monitor;
	if(*m0_);
	else if(tc)
	{
		vDELAY_STMR[vTASKING->TID] = tc;
		vTASKING->blocktype = ~tc ? __RECV_DM__ | __DELAY__ : __RECV_DM__;
		vTASKING->state = __BLOCKED__;
		vTASKING->ptr = (void *)m0_;
		vScheduling_f = true;
		mPSV_Trigger;
		__exit_critical();
		if(vTASKING->blocktype)
		{
			__enter_critical();
		}
		else
		{
			return false;
		}
	}
	else
	{
		__exit_critical();
		return false;
	}
	*m0_ = false;
	do{
		*m1++ = *++m0_;
	}while(--size);
	__exit_critical();
	return true;
}

#endif

#if SYSCFG_MAILBOX == __ENABLED__

void *__recv_mail(void *mbx, bool *nmf, bool *res, tDelay tc)
{
	mEntry_Monitor;
	if(*nmf)
	{
		*nmf = false;
		if(res != NULL)
		{
			*res = true;
		}
	}
	else if(tc)
	{
		vDELAY_STMR[vTASKING->TID] = tc;
		vTASKING->blocktype = ~tc ? __RECV_MAIL__ | __DELAY__ : __RECV_MAIL__;
		vTASKING->state = __BLOCKED__;
		vTASKING->ptr = nmf;
		vScheduling_f = true;
		mPSV_Trigger;
		__exit_critical();
		__enter_critical();
		if(vTASKING->blocktype)
		{
			*nmf = false;
			if(res != NULL)
			{
				*res = true;
			}
		}
		else if(res != NULL)
		{
			*res = false;
		}
	}
	else if(res != NULL)
	{
		*res = false;
	}
	return mbx;
}

#endif

#if SYSCFG_MSGQUEUE == __ENABLED__

tspMsgNode __recv_msg(tDelay tc)
{
	mEntry_Monitor;
	if(os_msg_head != NULL)
	{
		#if MCUCFG_MCULEVEL == __FEIPAOZI__
		vTASKING->ptr = (void *)os_msg_head;
		__exit_critical();
		return (tspMsgNode)vTASKING->ptr;
		#else
		__exit_critical();
		return os_msg_head;
		#endif
	}
	else if(tc)
	{
		vDELAY_STMR[vTASKING->TID] = tc;
		vTASKING->blocktype = ~tc ? __RECV_MSG__ | __DELAY__ : __RECV_MSG__;
		vTASKING->state = __BLOCKED__;
		vScheduling_f = true;
		mPSV_Trigger;
		__exit_critical();
		return (tspMsgNode)vTASKING->ptr;
	}
	else
	{
		__exit_critical();
		return NULL;
	}
}

#endif

#if SYSCFG_FLAGGROUP == __ENABLED__

bool __wait_grp(volatile void *p, u8 size, tDelay tc)
{
	mEntry_Monitor;
	{
		u8 type;
		switch(size)
		{
			case 1:
				if(*(u8 *)p) goto LABLE_1;
				else if(!tc) goto LABLE_2;
				type = __FLAGGROUP_1__;
			break;
			case 2:
				if(*(u16*)p) goto LABLE_1;
				else if(!tc) goto LABLE_2;
				type = __FLAGGROUP_2__;
			break;
			case 4:
				if(*(u32*)p) goto LABLE_1;
				else if(!tc) goto LABLE_2;
				type = __FLAGGROUP_4__;
			break;
			default: goto LABLE_2;
		}
		vDELAY_STMR[vTASKING->TID] = tc;
		vTASKING->blocktype = ~tc ? type | __DELAY__ : type;
		vTASKING->state = __BLOCKED__;
		vTASKING->ptr = (void *)p;
		vScheduling_f = true;
		mPSV_Trigger;
		__exit_critical();
		return (bool)vTASKING->blocktype;
		LABLE_1:
		__exit_critical();
		return true;
		LABLE_2:
		__exit_critical();
		return false;
	}
}

#endif

#if SYSCFG_DYNMEMMGE == __ENABLED__

void _MALLOC_MEM_ *__umalloc(size_t size)
{
	mEntry_Monitor;
	#if MCUCFG_MCULEVEL == __FEIPAOZI__
	{
		vTASKING->ptr = __malloc(size);
		__exit_critical();
		return vTASKING->ptr;
	}
	#else
	{
		register void _MALLOC_MEM_ *r = __malloc(size);
		__exit_critical();
		return r;
	}
	#endif
}

void _MALLOC_MEM_ *__ucalloc(size_t nmemb, size_t size)
{
	mEntry_Monitor;
	#if MCUCFG_MCULEVEL == __FEIPAOZI__
	{
		vTASKING->ptr = __calloc(nmemb, size);
		__exit_critical();
		return vTASKING->ptr;
	}
	#else
	{
		register void _MALLOC_MEM_ *r = __calloc(nmemb, size);
		__exit_critical();
		return r;
	}
	#endif
}

void _MALLOC_MEM_ *__urealloc(void _MALLOC_MEM_ *p, size_t size)
{
	mEntry_Monitor;
	#if MCUCFG_MCULEVEL == __FEIPAOZI__
	{
		vTASKING->ptr = __realloc(p, size);
		__exit_critical();
		return vTASKING->ptr;
	}
	#else
	{
		register void _MALLOC_MEM_ *r = __realloc(p, size);
		__exit_critical();
		return r;
	}
	#endif
}

void __ufree(void _MALLOC_MEM_ *p)
{
	mEntry_Monitor;
	__free(p);
	__exit_critical();
}

bool __uinit_mempool(tsThrmem *p, size_t size)
{
	mEntry_Monitor;
	p->p1 = p->p2 = __malloc(size);
	if(p->p1 == NULL)
	{
		__exit_critical();
		return false;
	}
	else
	{
		p->size = size;
		__exit_critical();
		return true;
	}
}

void _MALLOC_MEM_ *__utalloc(tsThrmem *p, size_t size)
{
	mEntry_Monitor;
	if(p->p1 == NULL || (size_t)p->p2 - (size_t)p->p1 + size > p->size)
	{
		__exit_critical();
		return NULL;
	}
	else
	{
		vTASKING->ptr = p->p2;
		p->p2 = (u8 *)p->p2 + size;
		__exit_critical();
		return vTASKING->ptr;
	}
}

#endif

void *__read_gary(void *lp, void *gp, size_t size)
{
	mEntry_Monitor;
	__memcpy(lp, gp, size);
	#if MCUCFG_MCULEVEL == __FEIPAOZI__
	vTASKING->ptr = lp;
	__exit_critical();
	return vTASKING->ptr;
	#else
	__exit_critical();
	return lp;
	#endif
}

void *__read_gstr(void *ls, void *gs)
{
	mEntry_Monitor;
	__strcpy(ls, gs);
	#if MCUCFG_MCULEVEL == __FEIPAOZI__
	vTASKING->ptr = ls;
	__exit_critical();
	return vTASKING->ptr;
	#else
	__exit_critical();
	return ls;
	#endif
}



#if SYSCFG_MCUCORE == 8051 || SYSCFG_MCUCORE == 80251
#pragma NOAREGS
#endif

#if SYSCFG_MAILBOX == __ENABLED__

void __send_mail(void *mbox, void *mail, size_t size, bool *nmf)
{
	#if MCUCFG_TASKSTACKMONITOR == __ENABLED__
	if(!vSTK_f) mEntry_Monitor;
	#endif
	{
		static tsMbxNode _SV_MEM_ mbx_node;
		mbx_node.gmbx = mbox;
		mbx_node.lmbx = mail;
		mbx_node.mbx_size = size;
		mbx_node.gnmf = nmf;
		mbx_node.lnmf = true;
		sWRITE_MBX_WRIT(&mbx_node);
		__memcpy(mbox, mail, size);
		sWRITE_MBX_WRIT(NULL);
		*mbx_node.gnmf = mbx_node.lnmf;
	}
}

#endif

#if SYSCFG_MSGQUEUE == __ENABLED__

void __send_msg(void *msg, void *des, size_t size, u8 type, void *free)
{
	#if MCUCFG_TASKSTACKMONITOR == __ENABLED__
	if(!vSTK_f) mEntry_Monitor;
	#endif
	{
		static tsMsgNode _SV_MEM_ msg_node;
		msg_node.msg_ptr = msg;
		msg_node.msg_des = des;
		msg_node.msg_size = size;
		msg_node.msg_type = type;
		msg_node.msg_free = free;
		msg_node.next = NULL;
		if(os_msg_tail != NULL)
		{
			os_msg_tail->next = &msg_node;
		}
		os_msg_tail = &msg_node;
		os_msg_tail->next = NULL;
		if(os_msg_head == NULL)
		{
			sWRITE_MSG_HEAD(os_msg_tail);
		}
	}
}

void __copy_msg(void *msg, void *des, size_t size, u8 type)
{
	#if MCUCFG_TASKSTACKMONITOR == __ENABLED__
	if(!vSTK_f) mEntry_Monitor;
	#endif
	{
		static tsMsgNode _SV_MEM_ msg_node;
		msg_node.msg_ptr = msg;
		msg_node.msg_des = des;
		msg_node.msg_size = size;
		msg_node.msg_type = type;
		msg_node.msg_free = NULL;
		msg_node.next = NULL;
		msg_node.msg_free = __malloc(size ? size : __strlen(msg) + 1);
		if(msg_node.msg_free == NULL)
		{
			vFault.malloc_fail_send_msg = true;
		}
		else
		{
			size ? __memcpy(msg_node.msg_free, msg, size) : __strcpy(msg_node.msg_free, msg);
			msg_node.msg_ptr = msg_node.msg_free;
			if(os_msg_tail != NULL)
			{
				os_msg_tail->next = &msg_node;
			}
			os_msg_tail = &msg_node;
			os_msg_tail->next = NULL;
			if(os_msg_head == NULL)
			{
				sWRITE_MSG_HEAD(os_msg_tail);
			}
		}
	}
}

void	__delete_msg(void)
{
	#if MCUCFG_TASKSTACKMONITOR == __ENABLED__
	if(!vSTK_f) mEntry_Monitor;
	#endif
	if(os_msg_head->msg_free == os_msg_head->msg_ptr)
	{
		__free(os_msg_head->msg_ptr);
		os_msg_head->msg_free = NULL;
	}
	else if(os_msg_head->msg_free != NULL)
	{
		*(bool *)os_msg_head->msg_free = true;
	}
	sWRITE_MSG_HEAD(os_msg_head->next);
	if(os_msg_head == NULL)
	{
		os_msg_tail = NULL;
	}
}

#endif

void *__write_gvar(void *gp, void *lp, size_t size)
{
	#if MCUCFG_TASKSTACKMONITOR == __ENABLED__
	if(!vSTK_f) mEntry_Monitor;
	#endif
	{
		static tsVarNode _SV_MEM_ var_node;
		var_node.gvar = gp;
		var_node.lvar = lp;
		var_node.var_size = size;
		sWRITE_VAR_WRIT(&var_node);
		size ? __memcpy(gp, lp, size) : __strcpy(gp, lp);
		sWRITE_VAR_WRIT(NULL);
		#if MCUCFG_MCULEVEL == __FEIPAOZI__
		vTASKING->ptr = gp;
		__exit_critical();
		return vTASKING->ptr;
		#else
		__exit_critical();
		return gp;
		#endif
	}
}

void __self_ope(void *gp, void *lp, size_t size, tfp_void_void fp)
{
	#if MCUCFG_TASKSTACKMONITOR == __ENABLED__
	if(!vSTK_f) mEntry_Monitor;
	#endif
	{
		static tsVarNode _SV_MEM_ var_node;
		var_node.gvar = gp;
		var_node.lvar = lp;
		var_node.var_size = size;
		sWRITE_VAR_WRIT(&var_node);
		(*fp)();
		sWRITE_VAR_WRIT(NULL);
	}
}
